package modularity.passiveDrift;

import java.util.Properties;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import ec.util.MersenneTwisterFast;

public class BasicMutatorManagerWithDuplication extends BasicMutatorManager implements MutationManager {

	protected double nodeDuplicationProb;

	public BasicMutatorManagerWithDuplication(Properties arguments) {
		super(arguments);
		this.nodeDuplicationProb = Double.valueOf(arguments.getProperty("remove-connection", "0.03"));
	}

	@Override
	public void mutate(ListedPopulation population)	throws InterruptedException {
		int populationsize = population.size();
		ExecutorService eservice = Executors.newFixedThreadPool(mutationThreads);
		CompletionService<Object> cservice = new ExecutorCompletionService<Object>(eservice);

		for(int i = 0; i < populationsize; i++){
			cservice.submit(new MutationTask(population.get(i), i, 
					new BasicMutatorWithNodeDuplication(removeConnectionProb, addConnectionProb, addNodeProb, nodeDuplicationProb), 
					new MersenneTwisterFast()));
		}

		eservice.shutdown();

		for(int index = 0; index < populationsize; index++) {
			Object result;
			try {
				result = cservice.take().get();
			} catch (InterruptedException e) {
				// Something went wrong with a task submitted
				System.out.println("Error Interrupted exception");
				e.printStackTrace();
				System.exit(0);
			} catch (ExecutionException e) {
				// Something went wrong with the result
				e.printStackTrace();
				System.out.println("Error get() threw exception");
				System.exit(0);
			}
		}
	}

	@Override
	public void setMutationThreads(int threads) {
		super.setMutationThreads(threads);
	}

}
